<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>

  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>4 加速 | Tidy evaluation</title>
  <meta name="description" content="这本书的目的是让你跟上 tidy evaluation 的进度，以及如何围绕 tidyverse 流程和语法编写函数" />
  <meta name="generator" content="bookdown 0.11 and GitBook 2.6.7" />

  <meta property="og:title" content="4 加速 | Tidy evaluation" />
  <meta property="og:type" content="book" />
  
  
  <meta property="og:description" content="这本书的目的是让你跟上 tidy evaluation 的进度，以及如何围绕 tidyverse 流程和语法编写函数" />
  <meta name="github-repo" content="ShixiangWang/tidyeval-chinese" />

  <meta name="twitter:card" content="summary" />
  <meta name="twitter:title" content="4 加速 | Tidy evaluation" />
  
  <meta name="twitter:description" content="这本书的目的是让你跟上 tidy evaluation 的进度，以及如何围绕 tidyverse 流程和语法编写函数" />
  

<meta name="author" content="Lionel Henry" />
<meta name="author" content="Hadley Wickham" />
<meta name="author" content="王诗翔（译）" />



  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  
  
<link rel="prev" href="sec-do-you-need.html">
<link rel="next" href="multiple.html">
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />







<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-115082821-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-115082821-1');
</script>


<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
  { content: attr(data-line-number);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>

<link rel="stylesheet" href="adv-r.css" type="text/css" />
</head>

<body>



  <div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">

    <div class="book-summary">
      <nav role="navigation">

<ul class="summary">
<li><strong><a href="./">Tidy evaluation</a></strong></li>

<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>欢迎</a><ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#e585b6e4bb96e8b584e6ba90"><i class="fa fa-check"></i>其他资源</a></li>
</ul></li>
<li class="part"><span><b>I 原理</b></span></li>
<li class="chapter" data-level="1" data-path="section-1.html"><a href="section-1.html"><i class="fa fa-check"></i><b>1</b> 介绍</a></li>
<li class="chapter" data-level="2" data-path="sec-why-how.html"><a href="sec-why-how.html"><i class="fa fa-check"></i><b>2</b> 为什么使用以及怎么使用</a><ul>
<li class="chapter" data-level="2.1" data-path="sec-why-how.html"><a href="sec-why-how.html#section-2.1"><i class="fa fa-check"></i><b>2.1</b> 数据隐藏</a></li>
<li class="chapter" data-level="2.2" data-path="sec-why-how.html"><a href="sec-why-how.html#section-2.2"><i class="fa fa-check"></i><b>2.2</b> 引用代码</a></li>
<li class="chapter" data-level="2.3" data-path="sec-why-how.html"><a href="sec-why-how.html#section-2.3"><i class="fa fa-check"></i><b>2.3</b> 去引用代码</a></li>
</ul></li>
<li class="chapter" data-level="3" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html"><i class="fa fa-check"></i><b>3</b> 你需要 tidy eval 吗？</a><ul>
<li class="chapter" data-level="3.1" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#sec:fixed-colnames"><i class="fa fa-check"></i><b>3.1</b> 固定列名</a></li>
<li class="chapter" data-level="3.2" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#sec:automating-loops"><i class="fa fa-check"></i><b>3.2</b> 自动循环</a><ul>
<li class="chapter" data-level="3.2.1" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#dplyr-"><i class="fa fa-check"></i><b>3.2.1</b> dplyr 中的向量化</a></li>
<li class="chapter" data-level="3.2.2" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#section-3.2.2"><i class="fa fa-check"></i><b>3.2.2</b> 按列循环</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="4" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html"><i class="fa fa-check"></i><b>4</b> 加速</a><ul>
<li class="chapter" data-level="4.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1"><i class="fa fa-check"></i><b>4.1</b> 编写函数</a><ul>
<li class="chapter" data-level="4.1.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1.1"><i class="fa fa-check"></i><b>4.1.1</b> 减少重复</a></li>
<li class="chapter" data-level="4.1.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1.2"><i class="fa fa-check"></i><b>4.1.2</b> 引用函数的特殊之处在哪？</a></li>
<li class="chapter" data-level="4.1.3" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1.3"><i class="fa fa-check"></i><b>4.1.3</b> 去引用</a></li>
<li class="chapter" data-level="4.1.4" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#-qq_show-"><i class="fa fa-check"></i><b>4.1.4</b> 通过 <code>qq_show()</code> 理解 <code>!!</code></a></li>
</ul></li>
<li class="chapter" data-level="4.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2"><i class="fa fa-check"></i><b>4.2</b> 引用和去引用</a><ul>
<li class="chapter" data-level="4.2.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.1"><i class="fa fa-check"></i><b>4.2.1</b> 第一步：抽取</a></li>
<li class="chapter" data-level="4.2.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.2"><i class="fa fa-check"></i><b>4.2.2</b> 第二步：引用</a></li>
<li class="chapter" data-level="4.2.3" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.3"><i class="fa fa-check"></i><b>4.2.3</b> 第三步：去引用</a></li>
<li class="chapter" data-level="4.2.4" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.4"><i class="fa fa-check"></i><b>4.2.4</b> 结果</a></li>
</ul></li>
<li class="chapter" data-level="4.3" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.3"><i class="fa fa-check"></i><b>4.3</b> 用字符串取代引用</a><ul>
<li class="chapter" data-level="4.3.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.3.1"><i class="fa fa-check"></i><b>4.3.1</b> 字符串</a></li>
<li class="chapter" data-level="4.3.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.3.2"><i class="fa fa-check"></i><b>4.3.2</b> 包含列名的字符串向量</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="5" data-path="multiple.html"><a href="multiple.html"><i class="fa fa-check"></i><b>5</b> Dealing with multiple arguments</a><ul>
<li class="chapter" data-level="5.1" data-path="multiple.html"><a href="multiple.html#the-...-argument"><i class="fa fa-check"></i><b>5.1</b> The <code>...</code> argument</a></li>
<li class="chapter" data-level="5.2" data-path="multiple.html"><a href="multiple.html#simple-forwarding-of-..."><i class="fa fa-check"></i><b>5.2</b> Simple forwarding of <code>...</code></a></li>
<li class="chapter" data-level="5.3" data-path="multiple.html"><a href="multiple.html#quote-multiple-arguments"><i class="fa fa-check"></i><b>5.3</b> Quote multiple arguments</a></li>
<li class="chapter" data-level="5.4" data-path="multiple.html"><a href="multiple.html#unquote-multiple-arguments"><i class="fa fa-check"></i><b>5.4</b> Unquote multiple arguments</a></li>
</ul></li>
<li class="chapter" data-level="6" data-path="modifying-inputs.html"><a href="modifying-inputs.html"><i class="fa fa-check"></i><b>6</b> Modifying inputs</a><ul>
<li class="chapter" data-level="6.1" data-path="modifying-inputs.html"><a href="modifying-inputs.html#modifying-names"><i class="fa fa-check"></i><b>6.1</b> Modifying names</a><ul>
<li class="chapter" data-level="6.1.1" data-path="modifying-inputs.html"><a href="modifying-inputs.html#default-argument-names"><i class="fa fa-check"></i><b>6.1.1</b> Default argument names</a></li>
<li class="chapter" data-level="6.1.2" data-path="modifying-inputs.html"><a href="modifying-inputs.html#unquoting-argument-names"><i class="fa fa-check"></i><b>6.1.2</b> Unquoting argument names</a></li>
<li class="chapter" data-level="6.1.3" data-path="modifying-inputs.html"><a href="modifying-inputs.html#prefixing-quoted-arguments"><i class="fa fa-check"></i><b>6.1.3</b> Prefixing quoted arguments</a></li>
</ul></li>
<li class="chapter" data-level="6.2" data-path="modifying-inputs.html"><a href="modifying-inputs.html#modifying-quoted-expressions"><i class="fa fa-check"></i><b>6.2</b> Modifying quoted expressions</a><ul>
<li class="chapter" data-level="6.2.1" data-path="modifying-inputs.html"><a href="modifying-inputs.html#expanding-quoted-expressions-with-expr"><i class="fa fa-check"></i><b>6.2.1</b> Expanding quoted expressions with <code>expr()</code></a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="7" data-path="glossary.html"><a href="glossary.html"><i class="fa fa-check"></i><b>7</b> Glossary</a><ul>
<li class="chapter" data-level="7.1" data-path="glossary.html"><a href="glossary.html#data-structures"><i class="fa fa-check"></i><b>7.1</b> Data structures</a><ul>
<li class="chapter" data-level="7.1.1" data-path="glossary.html"><a href="glossary.html#glossary-data-mask"><i class="fa fa-check"></i><b>7.1.1</b> TODO Data mask</a></li>
<li class="chapter" data-level="7.1.2" data-path="glossary.html"><a href="glossary.html#glossary-expr"><i class="fa fa-check"></i><b>7.1.2</b> Expression</a></li>
<li class="chapter" data-level="7.1.3" data-path="glossary.html"><a href="glossary.html#expression-base"><i class="fa fa-check"></i><b>7.1.3</b> Expression (base)</a></li>
<li class="chapter" data-level="7.1.4" data-path="glossary.html"><a href="glossary.html#glossary-sym"><i class="fa fa-check"></i><b>7.1.4</b> TODO Symbol</a></li>
</ul></li>
<li class="chapter" data-level="7.2" data-path="glossary.html"><a href="glossary.html#programming-concepts"><i class="fa fa-check"></i><b>7.2</b> Programming Concepts</a><ul>
<li class="chapter" data-level="7.2.1" data-path="glossary.html"><a href="glossary.html#glossary-constant-symbolic"><i class="fa fa-check"></i><b>7.2.1</b> Constant versus symbolic</a></li>
<li class="chapter" data-level="7.2.2" data-path="glossary.html"><a href="glossary.html#glossary-nse"><i class="fa fa-check"></i><b>7.2.2</b> TODO Non-Standard Evaluation (NSE)</a></li>
<li class="chapter" data-level="7.2.3" data-path="glossary.html"><a href="glossary.html#glossary-quotation-evaluation"><i class="fa fa-check"></i><b>7.2.3</b> TODO Quotation versus Evaluation</a></li>
<li class="chapter" data-level="7.2.4" data-path="glossary.html"><a href="glossary.html#glossary-qq"><i class="fa fa-check"></i><b>7.2.4</b> TODO Quasiquotation</a></li>
<li class="chapter" data-level="7.2.5" data-path="glossary.html"><a href="glossary.html#glossary-parse"><i class="fa fa-check"></i><b>7.2.5</b> TODO Parsing</a></li>
<li class="chapter" data-level="7.2.6" data-path="glossary.html"><a href="glossary.html#glossary-metaprogramming"><i class="fa fa-check"></i><b>7.2.6</b> TODO Metaprogramming</a></li>
</ul></li>
</ul></li>
<li class="part"><span><b>II Cookbooks</b></span></li>
<li class="chapter" data-level="8" data-path="dplyr.html"><a href="dplyr.html"><i class="fa fa-check"></i><b>8</b> dplyr</a><ul>
<li class="chapter" data-level="8.1" data-path="dplyr.html"><a href="dplyr.html#patterns-for-single-arguments"><i class="fa fa-check"></i><b>8.1</b> Patterns for single arguments</a><ul>
<li class="chapter" data-level="8.1.1" data-path="dplyr.html"><a href="dplyr.html#enquo-and---quote-and-unquote-arguments"><i class="fa fa-check"></i><b>8.1.1</b> <code>enquo()</code> and <code>!!</code> - Quote and unquote arguments</a></li>
<li class="chapter" data-level="8.1.2" data-path="dplyr.html"><a href="dplyr.html#quo_name---create-default-column-names"><i class="fa fa-check"></i><b>8.1.2</b> <code>quo_name()</code> - Create default column names</a></li>
<li class="chapter" data-level="8.1.3" data-path="dplyr.html"><a href="dplyr.html#and---unquote-column-names"><i class="fa fa-check"></i><b>8.1.3</b> <code>:=</code> and <code>!!</code> - Unquote column names</a></li>
</ul></li>
<li class="chapter" data-level="8.2" data-path="dplyr.html"><a href="dplyr.html#patterns-for-multiple-arguments"><i class="fa fa-check"></i><b>8.2</b> Patterns for multiple arguments</a><ul>
<li class="chapter" data-level="8.2.1" data-path="dplyr.html"><a href="dplyr.html#forward-multiple-arguments"><i class="fa fa-check"></i><b>8.2.1</b> <code>...</code> - Forward multiple arguments</a></li>
<li class="chapter" data-level="8.2.2" data-path="dplyr.html"><a href="dplyr.html#enquos-and---quote-and-unquote-multiple-arguments"><i class="fa fa-check"></i><b>8.2.2</b> <code>enquos()</code> and <code>!!!</code> - Quote and unquote multiple arguments</a></li>
<li class="chapter" data-level="8.2.3" data-path="dplyr.html"><a href="dplyr.html#expr---modify-quoted-arguments"><i class="fa fa-check"></i><b>8.2.3</b> <code>expr()</code> - Modify quoted arguments</a></li>
<li class="chapter" data-level="8.2.4" data-path="dplyr.html"><a href="dplyr.html#sec:external-quoting"><i class="fa fa-check"></i><b>8.2.4</b> <code>vars()</code> - Quote multiple arguments externally</a></li>
<li class="chapter" data-level="8.2.5" data-path="dplyr.html"><a href="dplyr.html#enquos.named-true---automatically-add-default-names"><i class="fa fa-check"></i><b>8.2.5</b> <code>enquos(.named = TRUE)</code> - Automatically add default names</a></li>
<li class="chapter" data-level="8.2.6" data-path="dplyr.html"><a href="dplyr.html#quos_auto_name---manually-add-default-names"><i class="fa fa-check"></i><b>8.2.6</b> <code>quos_auto_name()</code> - Manually add default names</a></li>
</ul></li>
<li class="chapter" data-level="8.3" data-path="dplyr.html"><a href="dplyr.html#select"><i class="fa fa-check"></i><b>8.3</b> <code>select()</code></a></li>
<li class="chapter" data-level="8.4" data-path="dplyr.html"><a href="dplyr.html#filter"><i class="fa fa-check"></i><b>8.4</b> <code>filter()</code></a></li>
<li class="chapter" data-level="8.5" data-path="dplyr.html"><a href="dplyr.html#case_when"><i class="fa fa-check"></i><b>8.5</b> <code>case_when()</code></a></li>
<li class="chapter" data-level="8.6" data-path="dplyr.html"><a href="dplyr.html#gotchas"><i class="fa fa-check"></i><b>8.6</b> Gotchas</a><ul>
<li class="chapter" data-level="8.6.1" data-path="dplyr.html"><a href="dplyr.html#nested-quoting-functions"><i class="fa fa-check"></i><b>8.6.1</b> Nested quoting functions</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="9" data-path="ggplot2.html"><a href="ggplot2.html"><i class="fa fa-check"></i><b>9</b> ggplot2</a></li>
<li class="part"><span><b>III Going further</b></span></li>
<li class="chapter" data-level="10" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html"><i class="fa fa-check"></i><b>10</b> A rich toolbox</a><ul>
<li class="chapter" data-level="10.1" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-quote-expr-and-enexpr"><i class="fa fa-check"></i><b>10.1</b> TODO <code>quote()</code>, <code>expr()</code> and <code>enexpr()</code></a></li>
<li class="chapter" data-level="10.2" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-quo-and-enquo"><i class="fa fa-check"></i><b>10.2</b> TODO <code>quo()</code> and <code>enquo()</code></a></li>
<li class="chapter" data-level="10.3" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-vars-quos-and-enquos"><i class="fa fa-check"></i><b>10.3</b> TODO <code>vars()</code>, <code>quos()</code> and <code>enquos()</code></a></li>
<li class="chapter" data-level="10.4" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#toolbox-qq-show"><i class="fa fa-check"></i><b>10.4</b> TODO <code>qq_show()</code></a></li>
<li class="chapter" data-level="10.5" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-sym-and-syms"><i class="fa fa-check"></i><b>10.5</b> TODO <code>sym()</code> and <code>syms()</code></a></li>
</ul></li>
<li class="chapter" data-level="11" data-path="creating-grammars.html"><a href="creating-grammars.html"><i class="fa fa-check"></i><b>11</b> Creating grammars</a></li>
</ul>

      </nav>
    </div>

    <div class="book-body">
      <div class="body-inner">
        <div class="book-header" role="navigation">
          <h1>
            <i class="fa fa-circle-o-notch fa-spin"></i><a href="./">Tidy evaluation</a>
          </h1>
        </div>

        <div class="page-wrapper" tabindex="-1" role="main">
          <div class="page-inner">

            <section class="normal" id="section-">
<div id="sec:up-to-speed" class="section level1">
<h1><span class="header-section-number">4</span> 加速</h1>
<p>While tidyverse grammars are easy to write in scripts and at the console, they make it a bit harder to reduce code duplication. Writing functions around dplyr pipelines and other tidyeval APIs requires a bit of special knowledge because these APIs use a special type of functions called <strong>quoting functions</strong> in order to make data first class.</p>
<p>If one-off code is often reasonable for common data analysis tasks, it is good practice to write reusable functions to reduce code duplication. In this introduction, you will learn about quoting functions, what challenges they pose for programming, and the solutions that <strong>tidy evaluation</strong> provides to solve those problems.</p>
<div id="section-4.1" class="section level2">
<h2><span class="header-section-number">4.1</span> 编写函数</h2>
<div id="section-4.1.1" class="section level3">
<h3><span class="header-section-number">4.1.1</span> 减少重复</h3>
<p>Writing functions is essential for the clarity and robustness of your code. Functions have several advantages:</p>
<ol style="list-style-type: decimal">
<li><p>They prevent inconsistencies because they force multiple computations to follow a single recipe.</p></li>
<li><p>They emphasise what varies (the arguments) and what is constant (every other component of the computation).</p></li>
<li><p>They make change easier because you only need to modify one place.</p></li>
<li><p>They make your code clearer if you give the function and its arguments informative names.</p></li>
</ol>
<p>The process for creating a function is straightforward. First, recognise duplication in your code. A good rule of thumb is to create a function when you have copy-pasted a piece of code three times. Can you spot the copy-paste mistake in this duplicated code?</p>
<pre class="sourceCode r"><code class="sourceCode r">(df<span class="op">$</span>a <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>a)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(df<span class="op">$</span>a) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>a))
(df<span class="op">$</span>b <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>b)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(df<span class="op">$</span>b) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>b))
(df<span class="op">$</span>c <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>c)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(df<span class="op">$</span>c) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>c))
(df<span class="op">$</span>d <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>d)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(df<span class="op">$</span>d) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(df<span class="op">$</span>c))</code></pre>
<p>Now identify the varying parts of the expression and give each a name. <code>x</code> is an easy choice, but it is often a good idea to reflect the type of argument expected in the name. In our case we expect a numeric vector:</p>
<pre class="sourceCode r"><code class="sourceCode r">(num <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(num) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num))
(num <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(num) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num))
(num <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(num) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num))
(num <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(num) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num))</code></pre>
<p>We can now create a function with a relevant name:</p>
<pre class="sourceCode r"><code class="sourceCode r">rescale01 &lt;-<span class="st"> </span><span class="cf">function</span>(num) {

}</code></pre>
<p>Fill it with our deduplicated code:</p>
<pre class="sourceCode r"><code class="sourceCode r">rescale01 &lt;-<span class="st"> </span><span class="cf">function</span>(num) {
  (num <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num)) <span class="op">/</span><span class="st"> </span>(<span class="kw">max</span>(num) <span class="op">-</span><span class="st"> </span><span class="kw">min</span>(num))
}</code></pre>
<p>And refactor a little to reduce duplication further and handle more cases:</p>
<pre class="sourceCode r"><code class="sourceCode r">rescale01 &lt;-<span class="st"> </span><span class="cf">function</span>(num) {
  rng &lt;-<span class="st"> </span><span class="kw">range</span>(num, <span class="dt">na.rm =</span> <span class="ot">TRUE</span>, <span class="dt">finite =</span> <span class="ot">TRUE</span>)
  (num <span class="op">-</span><span class="st"> </span>rng[[<span class="dv">1</span>]]) <span class="op">/</span><span class="st"> </span>(rng[[<span class="dv">2</span>]] <span class="op">-</span><span class="st"> </span>rng[[<span class="dv">1</span>]])
}</code></pre>
<p>Now you can reuse your function any place you need it:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">rescale01</span>(df<span class="op">$</span>a)
<span class="kw">rescale01</span>(df<span class="op">$</span>b)
<span class="kw">rescale01</span>(df<span class="op">$</span>c)
<span class="kw">rescale01</span>(df<span class="op">$</span>d)</code></pre>
<p>Reducing code duplication is as much needed with tidyverse grammars as with ordinary computations. Unfortunately, the straightforward process to create functions breaks down with grammars like dplyr, which we attach now.</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(<span class="st">&quot;dplyr&quot;</span>)</code></pre>
<p>To see the problem, let’s use the same function-writing process with a duplicated dplyr pipeline:</p>
<pre class="sourceCode r"><code class="sourceCode r">df1 <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">group_by</span>(x1) <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(y1))
df2 <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">group_by</span>(x2) <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(y2))
df3 <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">group_by</span>(x3) <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(y3))
df4 <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">group_by</span>(x4) <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(y4))</code></pre>
<p>We first abstract out the varying parts by giving them informative names:</p>
<pre class="sourceCode r"><code class="sourceCode r">data <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">group_by</span>(group_var) <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(summary_var))</code></pre>
<p>And wrap the pipeline with a function taking these argument names:</p>
<pre class="sourceCode r"><code class="sourceCode r">grouped_mean &lt;-<span class="st"> </span><span class="cf">function</span>(data, group_var, summary_var) {
  data <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">group_by</span>(group_var) <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(summary_var))
}</code></pre>
<p>Unfortunately this function doesn’t actually work. When you call it dplyr complains that the variable <code>group_var</code> is unknown:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">grouped_mean</span>(mtcars, cyl, mpg)
<span class="co">#&gt; Error: Column `group_var` is unknown</span></code></pre>
<p>Here is the proper way of defining this function:</p>
<pre class="sourceCode r"><code class="sourceCode r">grouped_mean &lt;-<span class="st"> </span><span class="cf">function</span>(data, group_var, summary_var) {
  group_var &lt;-<span class="st"> </span><span class="kw">enquo</span>(group_var)
  summary_var &lt;-<span class="st"> </span><span class="kw">enquo</span>(summary_var)

  data <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">group_by</span>(<span class="op">!!</span>group_var) <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(<span class="op">!!</span>summary_var))
}</code></pre>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">grouped_mean</span>(mtcars, cyl, mpg)
<span class="co">#&gt; # A tibble: 3 x 2</span>
<span class="co">#&gt;     cyl  mean</span>
<span class="co">#&gt;   &lt;dbl&gt; &lt;dbl&gt;</span>
<span class="co">#&gt; 1     4  26.7</span>
<span class="co">#&gt; 2     6  19.7</span>
<span class="co">#&gt; 3     8  15.1</span></code></pre>
<p>To understand how that works, we need to learn about quoting functions and what special steps are needed to be effective at programming with them. Really we only need two new concepts forming together a single pattern: quoting and unquoting. This introduction will get you up to speed with this pattern.</p>
</div>
<div id="section-4.1.2" class="section level3">
<h3><span class="header-section-number">4.1.2</span> 引用函数的特殊之处在哪？</h3>
<p>R functions can be categorised in two broad categories: evaluating functions and quoting functions <a href="#fn4" class="footnote-ref" id="fnref4"><sup>4</sup></a>. These functions differ in the way they get their arguments. Evaluating functions take arguments as <strong>values</strong>. It does not matter what the expression supplied as argument is or which objects it contains. R computes the argument value following the standard rules of evaluation which the function receives passively <a href="#fn5" class="footnote-ref" id="fnref5"><sup>5</sup></a>.</p>
<p>The simplest regular function is <code>identity()</code>. It evaluates its single argument and returns the value. Because only the final value of the argument matters, all of these statements are completely equivalent:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">identity</span>(<span class="dv">6</span>)
<span class="co">#&gt; [1] 6</span>

<span class="kw">identity</span>(<span class="dv">2</span> <span class="op">*</span><span class="st"> </span><span class="dv">3</span>)
<span class="co">#&gt; [1] 6</span>

a &lt;-<span class="st"> </span><span class="dv">2</span>
b &lt;-<span class="st"> </span><span class="dv">3</span>
<span class="kw">identity</span>(a <span class="op">*</span><span class="st"> </span>b)
<span class="co">#&gt; [1] 6</span></code></pre>
<p>On the other hand, a quoting function is not passed the value of an expression, it is passed the <em>expression itself</em>. We say the argument has been automatically quoted. The quoted expression might be evaluated a bit later or might not be evaluated at all. The simplest quoting function is <code>quote()</code>. It automatically quotes its argument and returns the quoted expression without any evaluation. Because only the expression passed as argument matters, none of these statements are equivalent:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">quote</span>(<span class="dv">6</span>)
<span class="co">#&gt; [1] 6</span>

<span class="kw">quote</span>(<span class="dv">2</span> <span class="op">*</span><span class="st"> </span><span class="dv">3</span>)
<span class="co">#&gt; 2 * 3</span>

<span class="kw">quote</span>(a <span class="op">*</span><span class="st"> </span>b)
<span class="co">#&gt; a * b</span></code></pre>
<p>Other familiar quoting operators are <code>&quot;&quot;</code> and <code>~</code>. The <code>&quot;&quot;</code> operator quotes a piece of text at parsing time and returns a string. This prevents the text from being interpreted as some R code to evaluate. The tilde operator is similar to the <code>quote()</code> function in that it prevents R code from being automatically evaluated and returns a quoted expression in the form of a formula. The expression is then used to define a statistical model in modelling functions. The three following expressions are doing something similar, they are quoting their input:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="st">&quot;a * b&quot;</span>
<span class="co">#&gt; [1] &quot;a * b&quot;</span>

<span class="op">~</span><span class="st"> </span>a <span class="op">*</span><span class="st"> </span>b
<span class="co">#&gt; ~a * b</span>

<span class="kw">quote</span>(a <span class="op">*</span><span class="st"> </span>b)
<span class="co">#&gt; a * b</span></code></pre>
<p>The first statement returns a quoted string and the other two return quoted code in a formula or as a bare expression.</p>
<div id="-r-" class="section level4">
<h4><span class="header-section-number">4.1.2.1</span> 在普通 R 代码中引用和计算</h4>
<p>As an R programmer, you are probably already familiar with the distinction between quoting and evaluating functions. Take the case of subsetting a data frame column by name. The <code>[[</code> and <code>$</code> operators are both standard for this task but they are used in very different situations. The former supports indirect references like variables or expressions that represent a column name while the latter takes a column name directly:</p>
<pre class="sourceCode r"><code class="sourceCode r">df &lt;-<span class="st"> </span><span class="kw">data.frame</span>(
  <span class="dt">y =</span> <span class="dv">1</span>,
  <span class="dt">var =</span> <span class="dv">2</span>
)

df<span class="op">$</span>y
<span class="co">#&gt; [1] 1</span>

var &lt;-<span class="st"> &quot;y&quot;</span>
df[[var]]
<span class="co">#&gt; [1] 1</span></code></pre>
<p>Technically, <code>[[</code> is an evaluating function while <code>$</code> is a quoting function. You can indirectly refer to columns with <code>[[</code> because the subsetting index is evaluated, allowing indirect references. The following expressions are completely equivalent:</p>
<pre class="sourceCode r"><code class="sourceCode r">df[[var]] <span class="co"># Indirect</span>
<span class="co">#&gt; [1] 1</span>

df[[<span class="st">&quot;y&quot;</span>]] <span class="co"># Direct</span>
<span class="co">#&gt; [1] 1</span></code></pre>
<p>But these are not:</p>
<pre class="sourceCode r"><code class="sourceCode r">df<span class="op">$</span>var    <span class="co"># Direct</span>
<span class="co">#&gt; [1] 2</span>

df<span class="op">$</span>y      <span class="co"># Direct</span>
<span class="co">#&gt; [1] 1</span></code></pre>
<p>The following table summarises the fundamental asymmetry between the two subsetting methods:</p>
<table>
<thead>
<tr class="header">
<th></th>
<th align="center">Quoted</th>
<th align="center">Evaluated</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Direct</td>
<td align="center"><code>df$y</code></td>
<td align="center"><code>df[[&quot;y&quot;]]</code></td>
</tr>
<tr class="even">
<td>Indirect</td>
<td align="center">???</td>
<td align="center"><code>df[[var]]</code></td>
</tr>
</tbody>
</table>
</div>
<div id="section-4.1.2.2" class="section level4">
<h4><span class="header-section-number">4.1.2.2</span> 检测引用函数</h4>
<p>Because they work so differently to standard R code, it is important to recognise auto-quoted arguments. The documentation of the quoting function should normally tell you if an argument is quoted and evaluated in a special way. You can also detect quoted arguments by yourself with some experimentation. Let’s take the following expressions involving a mix of quoting and evaluating functions:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(MASS)
<span class="co">#&gt; </span>
<span class="co">#&gt; 载入程辑包：&#39;MASS&#39;</span>
<span class="co">#&gt; The following object is masked from &#39;package:dplyr&#39;:</span>
<span class="co">#&gt; </span>
<span class="co">#&gt;     select</span>

mtcars2 &lt;-<span class="st"> </span><span class="kw">subset</span>(mtcars, cyl <span class="op">==</span><span class="st"> </span><span class="dv">4</span>)

<span class="kw">sum</span>(mtcars2<span class="op">$</span>am)
<span class="co">#&gt; [1] 8</span>

<span class="kw">rm</span>(mtcars2)</code></pre>
<p>A good indication that an argument is auto-quoted and evaluated in a special way is that the argument will not work correctly outside of its original context. Let’s try to break down each of these expressions in two steps by storing the arguments in an intermediary variable:</p>
<ol style="list-style-type: decimal">
<li><p><code>library(MASS)</code></p>
<pre class="sourceCode r"><code class="sourceCode r">temp &lt;-<span class="st"> </span>MASS
<span class="co">#&gt; Error in eval(expr, envir, enclos): 找不到对象&#39;MASS&#39;</span>

temp &lt;-<span class="st"> &quot;MASS&quot;</span>
<span class="kw">library</span>(temp)
<span class="co">#&gt; Error in library(temp): 不存在叫&#39;temp&#39;这个名字的程辑包</span></code></pre>
<p>We get these errors because there is no <code>MASS</code> object for R to find, and <code>temp</code> is interpreted by <code>library()</code> directly as a package name rather than as an indirect reference. Let’s try to break down the <code>subset()</code> expression:</p></li>
<li><p><code>mtcars2 &lt;- subset(mtcars, cyl == 4)</code></p>
<pre class="sourceCode r"><code class="sourceCode r">temp &lt;-<span class="st"> </span>cyl <span class="op">==</span><span class="st"> </span><span class="dv">4</span>
<span class="co">#&gt; Error in eval(expr, envir, enclos): 找不到对象&#39;cyl&#39;</span></code></pre>
<p>R cannot find <code>cyl</code> because we haven’t specified where to find it. This object exists only inside the <code>mtcars</code> data frame.</p></li>
<li><p><code>sum(mtcars2$am)</code></p>
<pre class="sourceCode r"><code class="sourceCode r">temp &lt;-<span class="st"> </span>mtcars<span class="op">$</span>am
<span class="kw">sum</span>(temp)
<span class="co">#&gt; [1] 13</span></code></pre>
<p>It worked! <code>sum()</code> is an evaluating function and the indirect reference was resolved in the ordinary way.</p></li>
<li><p><code>rm(mtcars2)</code></p>
<pre class="sourceCode r"><code class="sourceCode r">mtcars2 &lt;-<span class="st"> </span>mtcars
temp &lt;-<span class="st"> &quot;mtcars2&quot;</span>
<span class="kw">rm</span>(temp)

<span class="kw">exists</span>(<span class="st">&quot;mtcars2&quot;</span>)
<span class="co">#&gt; [1] TRUE</span>
<span class="kw">exists</span>(<span class="st">&quot;temp&quot;</span>)
<span class="co">#&gt; [1] FALSE</span></code></pre>
<p>This time there was no error, but we have accidentally removed the variable <code>temp</code> instead of the variable it was referring to. This is because <code>rm()</code> auto-quotes its arguments.</p></li>
</ol>
</div>
</div>
<div id="section-4.1.3" class="section level3">
<h3><span class="header-section-number">4.1.3</span> 去引用</h3>
<p>In practice, functions that evaluate their arguments are easier to program with because they support both direct and indirect references. For quoting functions, a piece of syntax is missing. We need the ability to <strong>unquote</strong> arguments.</p>
<div id="-r-" class="section level4">
<h4><span class="header-section-number">4.1.3.1</span> 基础 R 中的去引用</h4>
<p>Base R provides three different ways of allowing direct references:</p>
<ul>
<li><p>An extra function that evaluates its arguments. For instance the evaluating variant of the <code>$</code> operator is <code>[[</code>.</p></li>
<li><p>An extra parameter that switches off auto-quoting. For instance <code>library()</code> evaluates its first argument if you set <code>character.only</code> to <code>TRUE</code>:</p>
<pre class="sourceCode r"><code class="sourceCode r">temp &lt;-<span class="st"> &quot;MASS&quot;</span>
<span class="kw">library</span>(temp, <span class="dt">character.only =</span> <span class="ot">TRUE</span>)</code></pre></li>
<li><p>An extra parameter that evaluates its argument. If you have a list of object names to pass to <code>rm()</code>, use the <code>list</code> argument:</p>
<pre class="sourceCode r"><code class="sourceCode r">temp &lt;-<span class="st"> &quot;mtcars2&quot;</span>
<span class="kw">rm</span>(<span class="dt">list =</span> temp)

<span class="kw">exists</span>(<span class="st">&quot;mtcars2&quot;</span>)
<span class="co">#&gt; [1] FALSE</span></code></pre></li>
</ul>
<p>There is no general unquoting convention in base R so you have to read the documentation to figure out how to unquote an argument. Many functions like <code>subset()</code> or <code>transform()</code> do not provide any unquoting option at all.</p>
</div>
<div id="tidyverse-" class="section level4">
<h4><span class="header-section-number">4.1.3.2</span> tidyverse 中的去引用</h4>
<p>All quoting functions in the tidyverse support a single unquotation mechanism, the <code>!!</code> operator (pronounced <strong>bang-bang</strong>). You can use <code>!!</code> to cancel the automatic quotation and supply indirect references everywhere an argument is automatically quoted. In other words, unquoting lets you open a variable and use what’s inside instead.</p>
<p>First let’s create a couple of variables that hold references to columns from the <code>mtcars</code> data frame. A simple way of creating these references is to use the fundamental quoting function <code>quote()</code>:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="co"># Variables referring to columns `cyl` and `mpg`</span>
x_var &lt;-<span class="st"> </span><span class="kw">quote</span>(cyl)
y_var &lt;-<span class="st"> </span><span class="kw">quote</span>(mpg)

x_var
<span class="co">#&gt; cyl</span>

y_var
<span class="co">#&gt; mpg</span></code></pre>
<p>Here are a few examples of how <code>!!</code> can be used in tidyverse functions to unquote these variables, i.e. open them and use their contents.</p>
<ul>
<li><p>In dplyr most verbs quote their arguments:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(<span class="st">&quot;dplyr&quot;</span>)

by_cyl &lt;-<span class="st"> </span>mtcars <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">group_by</span>(<span class="op">!!</span>x_var) <span class="op">%&gt;%</span><span class="st">            </span><span class="co"># Open x_var</span>
<span class="st">  </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(<span class="op">!!</span>y_var))  <span class="co"># Open y_var</span></code></pre></li>
<li><p>In ggplot2 <code>aes()</code> is the main quoting function:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(<span class="st">&quot;ggplot2&quot;</span>)

<span class="kw">ggplot</span>(mtcars, <span class="kw">aes</span>(<span class="op">!!</span>x_var, <span class="op">!!</span>y_var)) <span class="op">+</span><span class="st">  </span><span class="co"># Open x_var and y_var</span>
<span class="st">  </span><span class="kw">geom_point</span>()</code></pre>
<p><img src="introduction_files/figure-html/unnamed-chunk-69-1.png" width="672" /></p>
<p>ggplot2 also features <code>vars()</code> which is useful for facetting:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">ggplot</span>(mtcars, <span class="kw">aes</span>(disp, drat)) <span class="op">+</span>
<span class="st">  </span><span class="kw">geom_point</span>() <span class="op">+</span>
<span class="st">  </span><span class="kw">facet_grid</span>(<span class="kw">vars</span>(<span class="op">!!</span>x_var))  <span class="co"># Open x_var</span></code></pre>
<p><img src="introduction_files/figure-html/unnamed-chunk-70-1.png" width="672" /></p></li>
</ul>
<p>Being able to make indirect references by opening variables with <code>!!</code> is rarely useful in scripts but is invaluable for writing functions. With <code>!!</code> we can now easily fix our wrapper function, as we’ll see in the following section.</p>
</div>
</div>
<div id="-qq_show-" class="section level3">
<h3><span class="header-section-number">4.1.4</span> 通过 <code>qq_show()</code> 理解 <code>!!</code></h3>
<p>At this point it is normal if the concept of unquoting still feels nebulous. A good way of practicing this operation is to see for yourself what it is really doing. To that end the <code>qq_show()</code> function from the rlang package performs unquoting and prints the result to the screen. Here is what <code>!!</code> is really doing in the dplyr example (I’ve broken the pipeline into two steps for readability):</p>
<pre class="sourceCode r"><code class="sourceCode r">rlang<span class="op">::</span><span class="kw">qq_show</span>(mtcars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">group_by</span>(<span class="op">!!</span>x_var))
<span class="co">#&gt; mtcars %&gt;% group_by(cyl)</span>

rlang<span class="op">::</span><span class="kw">qq_show</span>(data <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(<span class="op">!!</span>y_var)))
<span class="co">#&gt; data %&gt;% summarise(mean = mean(mpg))</span></code></pre>
<p>Similarly for the ggplot2 pipeline:</p>
<pre class="sourceCode r"><code class="sourceCode r">rlang<span class="op">::</span><span class="kw">qq_show</span>(<span class="kw">ggplot</span>(mtcars, <span class="kw">aes</span>(<span class="op">!!</span>x_var, <span class="op">!!</span>y_var)))
<span class="co">#&gt; ggplot(mtcars, aes(cyl, mpg))</span>

rlang<span class="op">::</span><span class="kw">qq_show</span>(<span class="kw">facet_grid</span>(<span class="kw">vars</span>(<span class="op">!!</span>x_var)))
<span class="co">#&gt; facet_grid(vars(cyl))</span></code></pre>
<p>As you can see, unquoting a variable that contains a reference to the column <code>cyl</code> is equivalent to directly supplying <code>cyl</code> to the dplyr function.</p>
</div>
</div>
<div id="section-4.2" class="section level2">
<h2><span class="header-section-number">4.2</span> 引用和去引用</h2>
<p>The basic process for creating tidyeval functions requires thinking a bit differently but is straightforward: quote and unquote.</p>
<ol style="list-style-type: decimal">
<li>Use <code>enquo()</code> to make a function automatically quote its argument.</li>
<li>Use <code>!!</code> to unquote the argument.</li>
</ol>
<p>Apart from these additional two steps, the process is the same.</p>
<div id="section-4.2.1" class="section level3">
<h3><span class="header-section-number">4.2.1</span> 第一步：抽取</h3>
<p>We start as usual by identifying the varying parts of a computation and giving them informative names. These names become the arguments to the function.</p>
<pre class="sourceCode r"><code class="sourceCode r">grouped_mean &lt;-<span class="st"> </span><span class="cf">function</span>(data, group_var, summary_var) {
  data <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">group_by</span>(group_var) <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(summary_var))
}</code></pre>
<p>As we have seen earlier this function does not quite work yet so let’s fix it by applying the two new steps.</p>
</div>
<div id="section-4.2.2" class="section level3">
<h3><span class="header-section-number">4.2.2</span> 第二步：引用</h3>
<p>The quoting step is about making our ordinary function a quoting function. Not all parameters should be automatically quoted though. For instance the <code>data</code> argument refers to a real data frame that is passed around in the ordinary way. It is crucial to identify which parameters of your function should be automatically quoted: the parameters for which it is allowed to refer to columns in the data frames. In the example, <code>group_var</code> and <code>summary_var</code> are the parameters that refer to the data.</p>
<p>We know that the fundamental quoting function is <code>quote()</code> but how do we go about creating other quoting functions? This is the job of <code>enquo()</code>. While <code>quote()</code> quotes what <em>you</em> typed, <code>enquo()</code> quotes what <em>your user</em> typed. In other words it makes an argument automatically quote its input. This is exactly how dplyr verbs are created! Here is how to apply <code>enquo()</code> to the <code>group_var</code> and <code>summary_var</code> arguments:</p>
<pre class="sourceCode r"><code class="sourceCode r">group_var &lt;-<span class="st"> </span><span class="kw">enquo</span>(group_var)
summary_var &lt;-<span class="st"> </span><span class="kw">enquo</span>(summary_var)</code></pre>
</div>
<div id="section-4.2.3" class="section level3">
<h3><span class="header-section-number">4.2.3</span> 第三步：去引用</h3>
<p>Finally we identify any place where these variables are passed to other quoting functions. That’s where we need to unquote with <code>!!</code>. In this case we pass <code>group_var</code> to <code>group_by()</code> and <code>summary_var</code> to <code>summarise()</code>:</p>
<pre class="sourceCode r"><code class="sourceCode r">data <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">group_by</span>(<span class="op">!!</span>group_var) <span class="op">%&gt;%</span>
<span class="st">  </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(<span class="op">!!</span>summary_var))</code></pre>
</div>
<div id="section-4.2.4" class="section level3">
<h3><span class="header-section-number">4.2.4</span> 结果</h3>
<p>The finished function looks like this:</p>
<pre class="sourceCode r"><code class="sourceCode r">grouped_mean &lt;-<span class="st"> </span><span class="cf">function</span>(data, group_var, summary_var) {
  group_var &lt;-<span class="st"> </span><span class="kw">enquo</span>(group_var)
  summary_var &lt;-<span class="st"> </span><span class="kw">enquo</span>(summary_var)

  data <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">group_by</span>(<span class="op">!!</span>group_var) <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(<span class="op">!!</span>summary_var))
}</code></pre>
<p>And voilà!</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">grouped_mean</span>(mtcars, cyl, mpg)
<span class="co">#&gt; # A tibble: 3 x 2</span>
<span class="co">#&gt;     cyl  mean</span>
<span class="co">#&gt;   &lt;dbl&gt; &lt;dbl&gt;</span>
<span class="co">#&gt; 1     4  26.7</span>
<span class="co">#&gt; 2     6  19.7</span>
<span class="co">#&gt; 3     8  15.1</span>

<span class="kw">grouped_mean</span>(mtcars, cyl, disp)
<span class="co">#&gt; # A tibble: 3 x 2</span>
<span class="co">#&gt;     cyl  mean</span>
<span class="co">#&gt;   &lt;dbl&gt; &lt;dbl&gt;</span>
<span class="co">#&gt; 1     4  105.</span>
<span class="co">#&gt; 2     6  183.</span>
<span class="co">#&gt; 3     8  353.</span>

<span class="kw">grouped_mean</span>(mtcars, am, disp)
<span class="co">#&gt; # A tibble: 2 x 2</span>
<span class="co">#&gt;      am  mean</span>
<span class="co">#&gt;   &lt;dbl&gt; &lt;dbl&gt;</span>
<span class="co">#&gt; 1     0  290.</span>
<span class="co">#&gt; 2     1  144.</span></code></pre>
<p>This simple quote-and-unquote pattern will get you a long way. It makes it possible to abstract complex combinations of quoting functions into a new quoting function. However this gets us in a sort of loop: quoting functions unquote inside other quoting functions and so on. At the start of the loop is the user typing expressions that are automatically quoted. But what if we can’t or don’t want to start with expressions typed by the user? What if we’d like to start with a character vector of column names?</p>
</div>
</div>
<div id="section-4.3" class="section level2">
<h2><span class="header-section-number">4.3</span> 用字符串取代引用</h2>
<p>So far we have created a quoting function that wraps around other quoting functions. How can we break this chain of quoting? How can we go from the evaluating world to the quoting universe? The most common way this transition occurs is when you start with a character vector of column names and somehow need to pass the corresponding columns to quoting functions like <code>dplyr::mutate()</code>, <code>dplyr::select()</code>, or <code>ggplot2::aes()</code>. We need a way of bridging evaluating and quoting functions.</p>
<p>First let’s see why simply unquoting strings does not work:</p>
<pre class="sourceCode r"><code class="sourceCode r">var &lt;-<span class="st"> &quot;height&quot;</span>
<span class="kw">mutate</span>(starwars, <span class="dt">rescaled =</span> <span class="op">!!</span>var <span class="op">*</span><span class="st"> </span><span class="dv">100</span>)
<span class="co">#&gt; Error in &quot;height&quot; * 100: 二进列运算符中有非数值参数</span></code></pre>
<p>We get a type error. Observing the result of unquoting with <code>qq_show()</code> will shed some light on this:</p>
<pre class="sourceCode r"><code class="sourceCode r">rlang<span class="op">::</span><span class="kw">qq_show</span>(<span class="kw">mutate</span>(starwars, <span class="dt">rescaled =</span> <span class="op">!!</span>var <span class="op">*</span><span class="st"> </span><span class="dv">100</span>))
<span class="co">#&gt; mutate(starwars, rescaled = &quot;height&quot; * 100)</span></code></pre>
<p>We have unquoted a string, and now dplyr tried to multiply that string by 100!</p>
<div id="section-4.3.1" class="section level3">
<h3><span class="header-section-number">4.3.1</span> 字符串</h3>
<p>There is a fundamental difference between these two objects:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="st">&quot;height&quot;</span>
<span class="co">#&gt; [1] &quot;height&quot;</span>

<span class="kw">quote</span>(height)
<span class="co">#&gt; height</span></code></pre>
<p><code>&quot;height&quot;</code> is a string and <code>quote(height)</code> is a <strong>symbol</strong>, or variable name. A symbol is much more than a string, it is a reference to an R object. That’s why you have to use symbols to refer to data frame columns. Fortunately transforming strings to symbols is straightforward with the tidy eval <code>sym()</code> function:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">sym</span>(<span class="st">&quot;height&quot;</span>)
<span class="co">#&gt; height</span></code></pre>
<p>If you use <code>sym()</code> instead of <code>enquo()</code>, you end up with an evaluating function that transforms its inputs into symbols that can suitably be unquoted:</p>
<pre class="sourceCode r"><code class="sourceCode r">grouped_mean2 &lt;-<span class="st"> </span><span class="cf">function</span>(data, group_var, summary_var) {
  group_var &lt;-<span class="st"> </span><span class="kw">sym</span>(group_var)
  summary_var &lt;-<span class="st"> </span><span class="kw">sym</span>(summary_var)

  data <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">group_by</span>(<span class="op">!!</span>group_var) <span class="op">%&gt;%</span>
<span class="st">    </span><span class="kw">summarise</span>(<span class="dt">mean =</span> <span class="kw">mean</span>(<span class="op">!!</span>summary_var))
}</code></pre>
<p>With this simple change we now have an <em>evaluating</em> wrapper which can be used in the same way as <code>[[</code>. You can call <code>grouped_mean2()</code> with direct references:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">grouped_mean2</span>(starwars, <span class="st">&quot;gender&quot;</span>, <span class="st">&quot;mass&quot;</span>)
<span class="co">#&gt; # A tibble: 5 x 2</span>
<span class="co">#&gt;   gender          mean</span>
<span class="co">#&gt;   &lt;chr&gt;          &lt;dbl&gt;</span>
<span class="co">#&gt; 1 &lt;NA&gt;            46.3</span>
<span class="co">#&gt; 2 female          NA  </span>
<span class="co">#&gt; 3 hermaphrodite 1358  </span>
<span class="co">#&gt; 4 male            NA  </span>
<span class="co">#&gt; 5 none            NA</span></code></pre>
<p>Or indirect references:</p>
<pre class="sourceCode r"><code class="sourceCode r">grp_var &lt;-<span class="st"> &quot;gender&quot;</span>
sum_var &lt;-<span class="st"> &quot;mass&quot;</span>
<span class="kw">grouped_mean2</span>(starwars, grp_var, sum_var)
<span class="co">#&gt; # A tibble: 5 x 2</span>
<span class="co">#&gt;   gender          mean</span>
<span class="co">#&gt;   &lt;chr&gt;          &lt;dbl&gt;</span>
<span class="co">#&gt; 1 &lt;NA&gt;            46.3</span>
<span class="co">#&gt; 2 female          NA  </span>
<span class="co">#&gt; 3 hermaphrodite 1358  </span>
<span class="co">#&gt; 4 male            NA  </span>
<span class="co">#&gt; 5 none            NA</span></code></pre>
</div>
<div id="section-4.3.2" class="section level3">
<h3><span class="header-section-number">4.3.2</span> 包含列名的字符串向量</h3>
<p>What if you have a whole character vector of column names? You can transform vectors to a list of symbols with the plural variant <code>syms()</code>:</p>
<pre class="sourceCode r"><code class="sourceCode r">cols &lt;-<span class="st"> </span><span class="kw">syms</span>(<span class="kw">c</span>(<span class="st">&quot;species&quot;</span>, <span class="st">&quot;gender&quot;</span>))

cols
<span class="co">#&gt; [[1]]</span>
<span class="co">#&gt; species</span>
<span class="co">#&gt; </span>
<span class="co">#&gt; [[2]]</span>
<span class="co">#&gt; gender</span></code></pre>
<p>But now we have a list. Can we just unquote a list of symbols with <code>!!</code>?</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">group_by</span>(starwars, <span class="op">!!</span>cols)
<span class="co">#&gt; Error: Column `&lt;list&gt;` must be length 87 (the number of rows) or one, not 2</span></code></pre>
<p>Something’s wrong. Using <code>qq_show()</code>, we see that <code>group_by()</code> gets a list instead of the individual symbols:</p>
<pre class="sourceCode r"><code class="sourceCode r">rlang<span class="op">::</span><span class="kw">qq_show</span>(<span class="kw">group_by</span>(starwars, <span class="op">!!</span>cols))
<span class="co">#&gt; group_by(starwars, &lt;list: species, gender&gt;)</span></code></pre>
<p>We should unquote each symbol in the list as a separate argument. The big bang operator <code>!!!</code> makes this easy:</p>
<pre class="sourceCode r"><code class="sourceCode r">rlang<span class="op">::</span><span class="kw">qq_show</span>(<span class="kw">group_by</span>(starwars, <span class="op">!!</span>cols[[<span class="dv">1</span>]], <span class="op">!!</span>cols[[<span class="dv">2</span>]]))
<span class="co">#&gt; group_by(starwars, species, gender)</span>

rlang<span class="op">::</span><span class="kw">qq_show</span>(<span class="kw">group_by</span>(starwars, <span class="op">!!!</span>cols))
<span class="co">#&gt; group_by(starwars, species, gender)</span></code></pre>
<p>Working with multiple arguments and lists of expressions requires specific techniques such as using <code>!!!</code>. These techniques are covered in the next chapter.</p>

</div>
</div>
</div>
<div class="footnotes">
<hr />
<ol start="4">
<li id="fn4"><p>In practice this is a bit more complex because most quoting functions evaluate at least one argument, usually the data argument.<a href="sec-up-to-speed.html#fnref4" class="footnote-back">↩</a></p></li>
<li id="fn5"><p>This is why regular functions are said to use standard evaluation unlike quoting functions which use non-standard evaluation (NSE). Note that the function is not entirely passive. Because arguments are lazily evaluated, the function gets to decide when an argument is evaluated, if at all.<a href="sec-up-to-speed.html#fnref5" class="footnote-back">↩</a></p></li>
</ol>
</div>
            </section>

          </div>
        </div>
      </div>
<a href="sec-do-you-need.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="multiple.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
    </div>
  </div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": false,
"google": false,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": ["facebook", "google", "twitter", "linkedin", "weibo", "instapaper"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": "https://github.com/ShixiangWang/tidyeval/edit/master/introduction.Rmd",
"text": "Edit"
},
"history": {
"link": null,
"text": null
},
"download": null,
"toc": {
"collapse": "section"
}
});
});
</script>

</body>

</html>
